import { useState, useCallback } from 'react'

export interface UseListOptions<T> {
  /** 初始数据 */
  initialData?: T[]
  /** 唯一键字段名 */
  idField?: keyof T
}

/**
 * useList Hook
 * 列表 CRUD 操作管理
 */
export const useList = <T extends Record<string, any>>({
  initialData = [],
  idField = 'id' as keyof T,
}: UseListOptions<T> = {}) => {
  const [items, setItems] = useState<T[]>(initialData)

  /**
   * 添加项
   */
  const add = useCallback((item: T) => {
    setItems((prev) => [...prev, item])
  }, [])

  /**
   * 批量添加
   */
  const addMultiple = useCallback((newItems: T[]) => {
    setItems((prev) => [...prev, ...newItems])
  }, [])

  /**
   * 插入项到指定位置
   */
  const insert = useCallback((index: number, item: T) => {
    setItems((prev) => {
      const newItems = [...prev]
      newItems.splice(index, 0, item)
      return newItems
    })
  }, [])

  /**
   * 更新项
   */
  const update = useCallback(
    (id: any, updates: Partial<T>) => {
      setItems((prev) =>
        prev.map((item) => (item[idField] === id ? { ...item, ...updates } : item))
      )
    },
    [idField]
  )

  /**
   * 替换项
   */
  const replace = useCallback(
    (id: any, newItem: T) => {
      setItems((prev) => prev.map((item) => (item[idField] === id ? newItem : item)))
    },
    [idField]
  )

  /**
   * 删除项
   */
  const remove = useCallback(
    (id: any) => {
      setItems((prev) => prev.filter((item) => item[idField] !== id))
    },
    [idField]
  )

  /**
   * 批量删除
   */
  const removeMultiple = useCallback(
    (ids: any[]) => {
      setItems((prev) => prev.filter((item) => !ids.includes(item[idField])))
    },
    [idField]
  )

  /**
   * 删除指定索引的项
   */
  const removeAt = useCallback((index: number) => {
    setItems((prev) => {
      const newItems = [...prev]
      newItems.splice(index, 1)
      return newItems
    })
  }, [])

  /**
   * 清空列表
   */
  const clear = useCallback(() => {
    setItems([])
  }, [])

  /**
   * 重置为初始数据
   */
  const reset = useCallback(() => {
    setItems(initialData)
  }, [initialData])

  /**
   * 设置整个列表
   */
  const setList = useCallback((newItems: T[]) => {
    setItems(newItems)
  }, [])

  /**
   * 查找项
   */
  const find = useCallback(
    (predicate: (item: T) => boolean): T | undefined => {
      return items.find(predicate)
    },
    [items]
  )

  /**
   * 根据 ID 查找项
   */
  const findById = useCallback(
    (id: any): T | undefined => {
      return items.find((item) => item[idField] === id)
    },
    [items, idField]
  )

  /**
   * 过滤列表
   */
  const filter = useCallback(
    (predicate: (item: T) => boolean): T[] => {
      return items.filter(predicate)
    },
    [items]
  )

  /**
   * 排序列表
   */
  const sort = useCallback((compareFn: (a: T, b: T) => number) => {
    setItems((prev) => [...prev].sort(compareFn))
  }, [])

  /**
   * 移动项
   */
  const move = useCallback((fromIndex: number, toIndex: number) => {
    setItems((prev) => {
      const newItems = [...prev]
      const [removed] = newItems.splice(fromIndex, 1)
      newItems.splice(toIndex, 0, removed)
      return newItems
    })
  }, [])

  /**
   * 切换项的属性（布尔值）
   */
  const toggle = useCallback(
    (id: any, field: keyof T) => {
      setItems((prev) =>
        prev.map((item) =>
          item[idField] === id ? { ...item, [field]: !item[field] } : item
        )
      )
    },
    [idField]
  )

  return {
    // 状态
    items,
    count: items.length,
    isEmpty: items.length === 0,

    // CRUD 方法
    add,
    addMultiple,
    insert,
    update,
    replace,
    remove,
    removeMultiple,
    removeAt,
    clear,
    reset,
    setList,

    // 查询方法
    find,
    findById,
    filter,

    // 其他方法
    sort,
    move,
    toggle,
  }
}

export default useList

